package mirrormonkey.rpc.tools.listeners;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

import java.util.Deque;
import java.util.LinkedList;

import mirrormonkey.rpc.RpcListener;
import mirrormonkey.rpc.module.RegisteredCall;

import com.jme3.network.MessageConnection;

public class MockRpcListener implements RpcListener {

	public final Deque<RpcEvent> recordedEvents;

	public MockRpcListener() {
		recordedEvents = new LinkedList<RpcEvent>();
	}

	@Override
	public void resultArrived(RegisteredCall registeredCall,
			MessageConnection source, Object result) {
		recordedEvents.addLast(new ResultEvent(registeredCall, source, result));
	}

	@Override
	public void errorArrived(RegisteredCall registeredCall,
			MessageConnection source, String message) {
		recordedEvents.addLast(new ErrorEvent(registeredCall, source, message));
	}

	@Override
	public void timedOut(RegisteredCall registeredCall) {
		recordedEvents.add(new TimeoutEvent(registeredCall));
	}

	public void checkResultArrived(MessageConnection source, Object result) {
		RpcEvent e = recordedEvents.pollFirst();
		assertEquals(ResultEvent.class, e.getClass());
		ResultEvent re = (ResultEvent) e;
		assertEquals(source, re.source);
		assertEquals(result, re.result);
	}

	public void checkResultSame(MessageConnection source, Object result) {
		RpcEvent e = recordedEvents.pollFirst();
		assertEquals(ResultEvent.class, e.getClass());
		ResultEvent re = (ResultEvent) e;
		assertEquals(source, re.source);
		assertSame(result, re.result);
	}

	public void checkErrorArrived(MessageConnection source, String message) {
		RpcEvent e = recordedEvents.pollFirst();
		assertEquals(ErrorEvent.class, e.getClass());
		ErrorEvent ee = (ErrorEvent) e;
		assertEquals(source, ee.source);
		assertEquals(message, ee.message);
	}

	public void checkTimeoutArrived() {
		RpcEvent e = recordedEvents.pollFirst();
		assertEquals(TimeoutEvent.class, e.getClass());
		TimeoutEvent te = (TimeoutEvent) e;
	}

	public static class RpcEvent {

		public final RegisteredCall call;

		public RpcEvent(RegisteredCall call) {
			this.call = call;
		}

	}

	public static class ResultEvent extends RpcEvent {

		public final MessageConnection source;

		public final Object result;

		public ResultEvent(RegisteredCall call, MessageConnection source,
				Object result) {
			super(call);
			this.source = source;
			this.result = result;
		}

	}

	public static class ErrorEvent extends RpcEvent {

		public final MessageConnection source;

		public final String message;

		public ErrorEvent(RegisteredCall call, MessageConnection source,
				String message) {
			super(call);
			this.source = source;
			this.message = message;
		}

	}

	public static class TimeoutEvent extends RpcEvent {

		public TimeoutEvent(RegisteredCall call) {
			super(call);
		}

	}

}
